package com.atguigu.gmall.cart.service.impl;

import com.atguigu.gmall.cart.service.CartService;
import com.atguigu.gmall.common.constant.RedisConst;
import com.atguigu.gmall.common.util.DateUtil;
import com.atguigu.gmall.model.cart.CartInfo;
import com.atguigu.gmall.model.product.SkuInfo;
import com.atguigu.gmall.product.client.ProductFeignClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class CartServiceImpl implements CartService {

    @Autowired
    private ProductFeignClient productFeignClient;

    @Autowired
    private RedisTemplate redisTemplate;

    @Override
    public void addToCart(Long skuId, String userId, Integer skuNum) {
        /**
         * 1、	商品详情页添加购物车redis
         * 2、	添加购物车，用户可以不需要登录，如果用户没有登录，则生成临时用户id，购物车商品与临时用户id关联，当用户登录后，将临时用户id的购物车商品与登录用户id的商品合并
         * 3、	商品详情添加购物车时，先判断用户是否登录，如果没登录，再判断是否存在临时用户，如果cookie中也没有临时用户，则生成临时用户
         */
        //生成key user:userId:cart
        String userKey = getCartKey(userId);
        //缓存中获取
        CartInfo cartInfoExits = (CartInfo) redisTemplate.boundHashOps(userKey).get(skuId.toString());
//        redisTemplate.opsForHash().get(userKey,skuId.toString());
        //如果不是第一次加入购物车就修改
        if (!StringUtils.isEmpty(cartInfoExits)){
            cartInfoExits.setSkuId(skuId);
            cartInfoExits.setSkuNum(cartInfoExits.getSkuNum()+skuNum);
            if (cartInfoExits.getIsChecked()==null){
                cartInfoExits.setIsChecked(1);
            }
            //远程调用去拿price
            BigDecimal skuPrice = productFeignClient.getSkuPrice(skuId);
            cartInfoExits.setSkuPrice(skuPrice);
            cartInfoExits.setUpdateTime(new Date());
        }else {

            cartInfoExits = new CartInfo();
            //  给cartInfo 赋值！
            SkuInfo skuInfo = productFeignClient.getSkuInfo(skuId);
            //  给表的字段赋值！
            cartInfoExits.setUserId(userId);
            cartInfoExits.setSkuId(skuId);
            cartInfoExits.setCartPrice(productFeignClient.getSkuPrice(skuId));
            cartInfoExits.setSkuNum(skuNum);
            cartInfoExits.setImgUrl(skuInfo.getSkuDefaultImg());
            cartInfoExits.setSkuName(skuInfo.getSkuName());
            cartInfoExits.setCreateTime(new Date());
            cartInfoExits.setUpdateTime(new Date());
            cartInfoExits.setSkuPrice(productFeignClient.getSkuPrice(skuId));

            //新增
//            CartInfo cartInfo = new CartInfo();
//            //  给cartInfo 赋值！
//            //  给表的字段赋值！
//            cartInfo.setUserId(userId);
//            cartInfo.setSkuId(skuId);
//            cartInfo.setCartPrice(skuInfo.getPrice());
//            cartInfo.setSkuNum(skuNum);
//            cartInfo.setImgUrl(skuInfo.getSkuDefaultImg());
//            cartInfo.setSkuName(skuInfo.getSkuName());
//            cartInfo.setCreateTime(new Date());
//            cartInfo.setUpdateTime(new Date());
//            cartInfo.setSkuPrice(skuInfo.getPrice());
        }
        //放入redis
        redisTemplate.boundHashOps(userKey).put(skuId.toString(), cartInfoExits);;
    }

    /**
     *
     *             1.  判断是否登录，根据判断结果查询不同的购物车！
     *             2.  查询的结果需要排序！
     *             3.  有可能需要合并！
     *                     在登录的情况下
     *                     .  未登录 ---> 登录合并！
     *                         合并完成之后，需要删除未登录购物车数据！
     *                      case1: 有userId ,没有userTempId
     *                      case2: 没有userId ,有userTempId   return noLoginCartInfoList
     *                      case3: 有userId ,有userTempId
     *                         登录情况下合并购物车：
     *                             先判断未登录购物车集合有数据！
     *                                 true: 有数据
     *                                     合并
     *                                 false: 没有数据
     *                                     只需要登录购物车数据
     *                             删除未登录购物车！
     *
     */
    @Override
    public List<CartInfo> getCartList(String userId, String userTempId) {
        //获取临时购物车信息
        List<CartInfo> noLoginCartInfoList=null;
        //未登录
        if (!StringUtils.isEmpty(userTempId)){
            //根据临时id ，key查询购物车
            //加入购物车
            noLoginCartInfoList=redisTemplate.opsForHash().values(getCartKey(userTempId));
        }

        //这个是集合的排序
        if (StringUtils.isEmpty(userId)){
            if (!CollectionUtils.isEmpty(noLoginCartInfoList)){
                //展示购物车列表的时候应该有顺序，按照修改时间排序
                noLoginCartInfoList.sort((o1, o2) -> {
                    //按照更新时间
                    return o2.getUpdateTime().compareTo(o1.getUpdateTime());
//                return DateUtil.truncatedCompareTo(o2.getUpdateTime(),o1.getUpdateTime(), Calendar.SECOND);
                });
            }
            //  返回未登录数据！
            return noLoginCartInfoList;
        }

        // 属于登录
        List<CartInfo> LoginCartInfoList=null;
        //获取登录购物车的value属性集合
        BoundHashOperations boundHashOperations1 = redisTemplate.boundHashOps(getCartKey(userId));
        //  判断购物车中的field
        //判断临时购物车不为空
        if (!CollectionUtils.isEmpty(noLoginCartInfoList)){
            //遍历未登录购物车集合
            noLoginCartInfoList.stream().forEach(cartInfo -> {
                //  在未登录购物车中的skuId 与登录的购物车skuId 相对  skuId = 17 18
                //判断公共部分，数量，时间，状态修改
                if (boundHashOperations1.hasKey(cartInfo.getSkuId().toString())){
                    //合并业务逻辑
                    CartInfo loginCartInfo = (CartInfo) boundHashOperations1.get(cartInfo.getSkuId().toString());
                    loginCartInfo.setSkuNum(loginCartInfo.getSkuNum()+cartInfo.getSkuNum());
                    loginCartInfo.setUpdateTime(new Date());
                    //最新价格
                    loginCartInfo.setSkuPrice(productFeignClient.getSkuPrice(cartInfo.getSkuId()));

                    //选中状态合并
                    if (cartInfo.getIsChecked().intValue()==1){
                        //修改登录选中状态
                        loginCartInfo.setIsChecked(1);
                    }
                    //修改缓存数据
                    boundHashOperations1.put(cartInfo.getSkuId().toString(),loginCartInfo);
                }else {
                    //直接添加缓存
                    cartInfo.setUserId(userId);
                    cartInfo.setCreateTime(new Date());
                    cartInfo.setUpdateTime(new Date());

                    boundHashOperations1.put(cartInfo.getSkuId().toString(),cartInfo);
                }
            });
            //删除未登录购物车的数据
            redisTemplate.delete(getCartKey(userTempId));
        }

        //  获取到合并之后的数据：
        LoginCartInfoList= redisTemplate.boundHashOps(getCartKey(userId)).values();
        //如果购物车为空，直接返回空
        if (CollectionUtils.isEmpty(LoginCartInfoList)){

            return new ArrayList<>();
        }

        //展示购物车列表的时候应该有顺序，按照修改时间排序
        LoginCartInfoList.sort((o1, o2) -> {
            return o2.getUpdateTime().compareTo(o1.getUpdateTime());
//                return DateUtil.truncatedCompareTo(o2.getUpdateTime(),o1.getUpdateTime(), Calendar.SECOND);
        });
        //返回购物车信息
        return LoginCartInfoList;
    }

    /**
     * 更新选中状态
     * @param userId
     * @param isChecked
     * @param skuId
     */
    @Override
    public void checkCart(String userId, Integer isChecked, Long skuId) {
        //获取购物车中的信息
        BoundHashOperations<String,String,CartInfo> boundHashOperations = redisTemplate.boundHashOps(getCartKey(userId));
        //获取单个购物项信息
        CartInfo cartInfo = boundHashOperations.get(skuId.toString());
        if (null !=cartInfo){
            //修改状态
            cartInfo.setIsChecked(isChecked);
        }
        //放入缓存
        boundHashOperations.put(skuId.toString(),cartInfo);
    }

    @Override
    public void deleteCart(Long skuId, String userId) {
        //查询购物车
        BoundHashOperations boundHashOperations = redisTemplate.boundHashOps(getCartKey(userId));
        //判断购物车中是否有此类商品
        if (boundHashOperations.hasKey(skuId.toString())){
            boundHashOperations.delete(skuId.toString());
        }
    }

    @Override
    public List<CartInfo> getCartCheckedList(String userId) {
        //获取选中购物车信息
        String cartKey = this.getCartKey(userId);
        //获取集合
        List<CartInfo> cartInfoList = redisTemplate.opsForHash().values(cartKey);
        //通过选中状态为1过滤
        List<CartInfo> cartInfos  = cartInfoList.stream().filter(cartInfo -> {
            //再次确定最新价格
            cartInfo.setSkuPrice(productFeignClient.getSkuPrice(cartInfo.getSkuId()));
            return cartInfo.getIsChecked().intValue() == 1;
        }).collect(Collectors.toList());

        return cartInfos;
    }

    /**
     * 购物车key
     * @param userId
     * @return
     */
    private String getCartKey(String userId) {
        return RedisConst.USER_KEY_PREFIX+userId+RedisConst.USER_CART_KEY_SUFFIX;
    }
}
